package com.feather.common.util;

import java.lang.reflect.InvocationTargetException;
import java.util.Map;

/**
 * @author flogyin
 */
public class RuntimeError extends RuntimeException {
	private static final long	serialVersionUID	= 601036281579370242L;

	public Throwable			error;

	public Object				source;
	public String				method;
	public Map<String, ?>		params;
	public Object				relative;

	public boolean				hasPrint;
	public boolean				hasLog;

	private RuntimeError() {
	}

	public RuntimeError(String message) {
		super(message);
	}

	public static RuntimeError create(Throwable cause) {
		RuntimeError error = new RuntimeError();
		error.error = cause;
		return error;
	}

	public static RuntimeError create(Throwable cause, Object source, String method, Map<String, ?> params) {
		if (cause instanceof RuntimeError) {
			return (RuntimeError) cause;
		}
		RuntimeError error = new RuntimeError();
		error.error = cause;
		error.source = source;
		error.method = method;
		error.params = params;
		return error;
	}

	public static RuntimeError create(Throwable cause, Object source, String method, Map<String, Object> params, Object relative) {
		if (cause instanceof RuntimeError) {
			return (RuntimeError) cause;
		}
		RuntimeError error = new RuntimeError();
		error.error = cause;
		error.source = source;
		error.method = method;
		error.params = params;
		error.relative = relative;
		return error;
	}

	public static Throwable getInner(Throwable throwable) {
		if (throwable instanceof InvocationTargetException) {
			throwable = ((InvocationTargetException) throwable).getTargetException();
		}
		if (throwable instanceof RuntimeError) {
			RuntimeError me = (RuntimeError) throwable;
			if (me.error != null) {
				throwable = me.error;
				if (throwable instanceof RuntimeError)
					throwable = getInner(throwable);
			}
		}
		return throwable;
	}

	public static String getMessage(Throwable throwable) {
		return getCaption(throwable)[1];
	}

	public static String getCode(Throwable throwable) {
		return getCaption(throwable)[0];
	}

	public static String[] getCaption(Throwable throwable) {
		String[] info = new String[] { "", "" };
		throwable = getInner(throwable);
		if (throwable != null) {
			if (throwable instanceof InvocationTargetException) {
				throwable = ((InvocationTargetException) throwable).getTargetException();
			}
			if (throwable instanceof RuntimeError) {
				throwable = ((RuntimeError) throwable).error;
			}
			String message = throwable.getMessage();
			if (message != null) {
				int newLineAt = message.indexOf('\n');
				if (newLineAt > 0) {
					message = message.substring(0, newLineAt);
				}
				info[1] = message;
				int atStart = message.indexOf("#[");
				int atEnd = message.indexOf("]");
				if (atStart > -1 && atEnd > atStart) {
					info[0] = message.substring(atStart + 2, atEnd);
					info[1] = message.substring(atEnd + 1);
				} else if (message.startsWith("ORA")) {// ORA-20000:
					String colon = ": ";
					int colonAt = message.indexOf(colon);
					if (colonAt > 4) {
						info[0] = message.substring(4, colonAt);
						info[1] = message.substring(colonAt + 2);
					}
				}
			} else {
				info[1] = throwable.toString();
			}
		}
		return info;
	}

	public static String getErrorCause(Throwable cause) {
		StringBuilder builder = new StringBuilder();
		if (cause != null) {
			if (cause instanceof RuntimeError) {
				RuntimeError me = (RuntimeError) cause;
				if (me.error != null)
					cause = me.error;
			}
			/*
			 * String caption = cause.getMessage(); if (caption != null) {
			 * builder.append(caption); builder.append("\n"); }
			 */
			builder.append(cause.toString());

			StackTraceElement[] stackTrace = cause.getStackTrace();
			for (StackTraceElement e : stackTrace) {
				builder.append("\n");
				builder.append(e.toString());
			}
		}
		return builder.toString();
	}

	public static void main(String[] args) {
		System.out.println("abc#[123]xxx".substring(3 + 2, 8));
	}
}
